/*
 * @file     g_uart.h
 * @brief    source file for setting uart
 *
 * Change Logs:
 * Date            Author             Version        Notes
 * 2020-11-06      wushengyan         V1.0.0         the first version
 */

#include "g_otp.h"
#include "g_rom_api.h"

#define OTP_WRITE_CHGPUMP_CFG   0x43

/**
 * @method G_OTP_Init
 * @brief  init otp module
 * @param  NULL
 * @retval NULL
 */
void G_OTP_Init(void)
{
    ((void(*)())FUNC_INIT_OTP_ADDR)();
}

/**
 * @method G_OTP_Deinit
 * @brief  deinit otp module
 * @param  NULL
 * @retval NULL
 */
void G_OTP_Deinit(void)
{
    ((void(*)())FUNC_DEINIT_OTP_ADDR)();
}

/**
 * @method G_OTP_Read_ChipId
 * @brief  read chipid
 * @param  id:id out buf(6byte)
 * @retval NULL
 */
void G_OTP_Read_ChipId(uint8_t *id)
{
    G_OTP_Init();
    ((void(*)(uint8_t *id))FUNC_READ_CHIPID_ADDR)(id);
    G_OTP_Deinit();
}

/**
 * @method read_chip life
 * @brief  read chip life
 * @param  NULL
 * @retval 0x0000-->test stage
 *         0x1111-->debug stage
 *         0x7777-->product stage
 */
uint32_t G_OTP_Read_ChipLife(void)
{
    uint32_t life = 0;
    G_OTP_Init();
    life = ((uint32_t(*)(void))FUNC_READ_CHIPLF_ADDR)();
    G_OTP_Deinit();
    return life;
}

/**
 * @method read otp data
 * @brief  read otp data
 * @param  addr:   0~0x1fff
 * @param  *data:  read data buf ptr
 * @param  len:    read data len
 * @retval SUCCESS / ERROR
 */
uint8_t G_OTP_Read(uint32_t addr, uint8_t *data, uint32_t len)
{
    G_OTP_Init();
    ((uint8_t(*)(uint32_t addr, uint8_t *data, uint32_t len))FUNC_READ_OTP_ADDR)(addr, data, len);
    G_OTP_Deinit();
    return SUCCESS;
}

uint8_t G_OTP_DataXOR(uint32_t data,uint8_t bit)
{
    uint8_t xor_val = 0;
    for(uint8_t i = 0; i< bit; i++)
    {
        xor_val ^= (data >> i) & 0x01;
    }
    return xor_val;
}

static uint32_t Get_WriteChgrpumpConfig()
{
    uint8_t readbuf[2] = {0};
    uint32_t chgpumpconfig = 0;
    G_OTP_Read(OTP_CHGPUMPADDR,readbuf,OTP_CHGPUMPLEN);
    chgpumpconfig = (readbuf[0] | (readbuf[1] << 8));
    uint8_t xorbit  = G_OTP_DataXOR(chgpumpconfig,9);
    uint8_t enable = (chgpumpconfig >> 15) & 0x01;
    
    if(enable && (xorbit == ((chgpumpconfig >> 14) & 0x01)))
    {
        return (chgpumpconfig & 0x3ff);
    }
    
    return OTP_WRITE_CHGPUMP_CFG;
}

/*
 * @method write otp data
 * @brief:  OTP write
 * @param:  addr:  0~0x1fff
 * @param:  *data: write data buf ptr
 * @param:  len:   write data len
 * @return: SUCCESS or ERROR
 */
uint8_t G_OTP_Write(uint32_t addr, uint8_t *data, uint32_t len)
{
    uint32_t chgpumpconfig = 0;
    chgpumpconfig = Get_WriteChgrpumpConfig();
    return ((uint8_t(*)(uint32_t addr, uint8_t *data, uint32_t len, uint32_t chgpumpconfig))FUNC_WRITE_OTP_ADDR)(addr, data, len,chgpumpconfig );
}
